#include "bus.h"

#define BUS_TEMPLATE    template<\
                            typename word_t, \
                            typename cpu_t , \
                            typename mem_t , \
                            typename disk_t, \
                            typename mdev_t  \
                        >    

#define BUS_CLASS       BUS<word_t, cpu_t, mem_t, disk_t, mdev_t>

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

/**
 * 功能：
 * @brief : 
 *      初始化总线
 */
BUS_TEMPLATE
void BUS_CLASS::init() {
    /* CPU 外部接口初始化 */
    cpu.load   = BUS_CLASS::rfm  ;
    cpu.store  = BUS_CLASS::wtm  ;
    cpu.inchar = BUS_CLASS::icfd ;
    cpu.outc   = BUS_CLASS::octd ;
    cpu.outs   = BUS_CLASS::ostd ;
    cpu.flush  = BUS_CLASS::ftd  ;

    /* 内存外部借口初始化 */
    mem.read_key   = BUS_CLASS::rfk ;
    mem.check_key  = BUS_CLASS::skc ;
    mem.load_image = BUS_CLASS::lifd ;
}

/**
 * @brief : 
 *      从内存读入数据到总线
 *      read from memory
  * @param : 
 *      word_t addr : 内存地址
 * @return : 
 *      word_t : 返回读入的数据
 */
BUS_TEMPLATE
word_t BUS_CLASS::rfm(word_t addr){
    return mem.read(addr);
}

BUS_TEMPLATE
word_t BUS_CLASS::rfk(){
    return (word_t)dev.inchar();
}

/**
 * @brief : 
 *      从内存读入数据到总线
 *      write to memory
  * @param : 
 *      word_t addr : 内存地址
 *      word_t data : 待写入内存的数据
 */
BUS_TEMPLATE
void BUS_CLASS::wtm(word_t addr, word_t data) {
    mem.write(addr, data);
}

/**
 * @brief : 
 *      从外部设备读入一个字符到总线
 *      input char from dev
 * @return : 
 *      char : 返回读入的字符
 */
BUS_TEMPLATE
char BUS_CLASS::icfd(){
    return dev.inchar();
}

/**
 * @brief : 
 *      输出一个字符到外部设备
 *      output char to dev
  * @param : 
 *      char c : 待输出的字符
 */
BUS_TEMPLATE
void BUS_CLASS::octd(char c){
    return dev.outc(c);
}

/**
 * @brief : 
 *      输出一个字符串到外部设备
 *      output char to dev
  * @param : 
 *      const char* str : 待输出的字符串
 */
BUS_TEMPLATE
void BUS_CLASS::ostd(const char* str){
    return dev.outs(str);
}

/**
 * @brief : 
 *      刷新外部设备
 *      flush to dev
 */
BUS_TEMPLATE
void BUS_CLASS::ftd(){
    return dev.flush();
}

/**
 * @brief : 
 *      按键检测
 *      strike key check
 * @return : 
 *      int : 若按键被按下，返回 1，否者返回 0
 */
BUS_TEMPLATE
int BUS_CLASS::skc(){
    return dev.check_key();
}

BUS_TEMPLATE
void BUS_CLASS::lifd(){
    /* 首先获取内存地址 */
    word_t origin;
    disk.request_addr(&origin, sizeof(word_t));

    /* 转换为小端模式 */
    origin = mem.swap16(origin);

    /* 将磁盘中的内容读取到内存指定位置 */
    word_t* p = mem.alloc_addr(origin);
    word_t  max_read = mem.get_memsize() - origin;
    int read_bytes = disk.load_image( (void *)p, max_read * sizeof(word_t));

    /* 将读入的内容转换为小端存储 */
    while( 0 < read_bytes ) {
        *p = mem.swap16(*p);
        p++;
        read_bytes -= sizeof(word_t);
    }
}
